PSR-4 的誕生,歸功於 PSR-0: Autoloading Standard (自動載入標準),因為 PSR-0 的 命名方式有些攏長,導致在使用上會有些難使用,但 FIG 是建議不使用PSR-0,以 PSR-4為代替。不建議回去看PSR-0,可能會跟PSR-4搞混。

規則

  • 必須(MUST):嚴格遵循,無條件照作及遵守。
  • 不可(MUST NOT):禁止、嚴格禁止。
  • 必要(REQUIRED):
  • 將要(SHALL):
  • 將不(SHALL NOT):
  • 應該(SHOULD):強烈建議這樣做,但不會強求。
  • 不應該(SHOULD NOT):強烈不建議這樣做,但不會強求。
  • 建議、推薦(RECOMMENDED):
  • 可以/可能(MAY)和選用/可選(OPTIONAL)

以上作為做解釋性的描述。參考 RFC 2119

自動載入?

描述了如何架構專案的目錄結構及如何使用命名空間,composer 提供的 autoload 就可以完成自動載入的動作。要使用 PSR-4 Autoloader 必須使用正確的命名方式

1
2
\<命名空間>(\<子命名空間>)*\<類名>
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
  1. 完整 class 名稱 “必須” 包含頂層命名空間名稱,也被稱為供應者命名空間(vendor namespace)。
  2. 完整 class 名稱 “可能” 包含一個或更多個子命名空間名稱。
  3. 完整 class 名稱 “必須” 包含一個尾端類別名稱
  4. 底線在完整 class 名稱的任何位置都沒有特殊意義。
  5. 完整 class 名稱裡的英文字母 “可以” 是大小寫混合。
  6. 所有 class 名稱 “必須” 以區分大小寫的方式被參考。

實作練習

建立以下資料夾及PHP檔案。

專案 > public 資料夾假設當作是網頁的進入點。
專案 > src 未來增加的類別進而幫助網頁可更好維護等。

  • 建立專案名稱:DemoPSR4-Autoloader

建立依賴檔案(composer.json)

1
專案名稱 % composer init

建立好的依賴檔案,可能會是下面這樣,看個人的設定。

專案 > composer.json

1
2
3
4
5
6
7
8
9
10
11
{
"name": "kuo/demo-psr4-autoloader",
"description": "demo",
"authors": [
{
"name": "black",
"email": "abc123@abc.com"
}
],
"require": {},
}

接著下載安裝 dump-autoload 的套件,dump-autoload 是一種自動加載的套件,之後會產生 專案 > vendor 這個資料夾,裡面會放所需的套件。

1
2
3
4
專案名稱 % composer dump-autoload

# 等同上方的指令
專案名稱 % composer dump

下載完dump-autoload 的套件以後,接著編輯 composer.json ,增加 autoload 的屬性,設定前綴及資料夾 { "自訂定義命名空間前綴": "指定資料夾" } ,其實不寫前綴也可以,可以直接把前綴設置空白{ "": "src/" }

專案 > composer.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name": "kuo/demo-psr4-autoloader",
"description": "demo",
"authors": [
{
"name": "black",
"email": "abc123@abc.com"
}
],
"require": {},
"autoload": {
"psr-4": {
"MyApp\\": "src/"
}
}
}

接著就是在各頁面簡單寫一段程式。

namespace 又稱命名空間,在前一段程式碼,我們有設定前綴的部分, MyApp 等於指定 src 這個資料夾。

格式:命名空間前綴/過度路徑/檔案.php
實際上:MyApp/book/papper/talk.php

__construct 是 PHP 的建構子(保留字),當執行 Talk 這個類別的時候,就會執行他的建構子,但通常都是放必要執行的程式,例如資料庫連線之類的。可參考 [PHP] 類別的繼承及建構子和解構子

專案 > src > book > papper > talk.php

1
2
3
4
5
6
7
8
9
<?php

namespace MyApp\book\papper;

class Talk{
function __construct(){
echo '大家說英文</br>';
}
}

下面 ebook.phpapple.php 設置跟上方都差不多,差別在於路徑要注意。

格式:命名空間前綴/過度路徑/檔案.php
實際上:MyApp/book/ebook.php

專案 > src > book > ebook.php

1
2
3
4
5
6
7
8
9
<?php

namespace MyApp\book;

class ebook{
function __construct(){
echo '電子書</br>';
}
}

格式:命名空間前綴/過度路徑/檔案.php
實際上:MyApp/food/apple.php

專案 > src > food > apple.php

1
2
3
4
5
6
7
8
9
<?php

namespace MyApp\food;

class apple{
function __construct(){
echo '食物-蘋果</br>';
}
}

之前有說過,public 當成網頁的進入點,所以我們在這裡將剛剛設置好的class 引入進來使用。

  1. 引入 autoload 的套件
  2. 引入各 class 。 由於我們有設定前綴,所以只要用前綴做代替。
  3. 將各 class 建立成物件

專案 > public > index.php

1
2
3
4
5
6
7
8
9
10
11
<?php
require_once "../vendor/autoload.php";

// 方法1
use MyApp\book\papper\Talk;
use MyApp\book\ebook;
use MyApp\food\apple;

$Talk = new Talk();
$ebook = new ebook();
$apple = new apple();

跟上方會是同樣的結果,但只是換個方式呈現。

1
2
3
4
5
6
7
<?php
require_once "../vendor/autoload.php";

// 方法2
$Talk = new MyApp\book\papper\Talk();
$ebook = new MyApp\book\ebook();
$apple = new MyApp\food\apple();

結果

參考文件

tags: w3HexSchool PHP PSR